package com.lst.api.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lst.api.config.SecretConfig;
import com.lst.api.vo.AccessTokenVo;
import com.lst.tools.custom.annotation.TokenPermission;
import com.lst.tools.custom.constants.TokenConstants;
import com.lst.tools.custom.context.BaseContextHandler;
import com.lst.tools.custom.utils.JwtHelper;
import com.lst.tools.redis.service.impl.RedisService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * JWT 工具类
 *
 * @author: Frank
 * @date: 2019/09/24 13:51
 * @version: V1.0
 */
@Configuration
public class TokenUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(TokenUtil.class);

    @Autowired
    private SecretConfig secretConfig;
    @Autowired
    private RedisService redisService;

    public String generateToken(Map<String, Object> claims) throws Exception {
        return JwtHelper.generateToken(claims, secretConfig.getAccessTokenPriKey(), secretConfig.getAccessTokenExpire());
    }

    public String generateTicket(Map<String, Object> claims) throws Exception {
        return JwtHelper.generateToken(claims, secretConfig.getAccessTokenPriKey(), null);
    }

    public boolean isLegal(String originTicket, TokenPermission tokenPermission) {
        try {
            if (StringUtils.isBlank(originTicket)) {
                BaseContextHandler.remove();
                return tokenPermission == null;
            }
            int originTicketLength = originTicket.length();
            String ticket = originTicket.substring(TokenConstants.ACCESS_TOKEN_HEADER_PREFIX.length(), originTicketLength);
            Map<String, Object> claims = JwtHelper.parserToken(ticket, secretConfig.getAccessTokenPubKey());
            String scope = (String) claims.get(TokenConstants.SCOPE_KEY);
            if (!TokenConstants.TICKET_SCOPE.equals(scope)) {
                BaseContextHandler.remove();
                return tokenPermission == null;
            }
            String redisKey = (String) claims.get(TokenConstants.USER_TOKEN_REDIS_KEY);
            if (StringUtils.isBlank(redisKey)) {
                BaseContextHandler.remove();
                return tokenPermission == null;
            }
            String tokenJson = redisService.get(redisKey);
            if (StringUtils.isBlank(tokenJson)) {
                BaseContextHandler.remove();
                return tokenPermission == null;
            }
            //每次ticket都不一样
            String random = (String) claims.get(TokenConstants.TICKET_RANDOM_KEY);
            AccessTokenVo accessTokenVo = JSON.parseObject(tokenJson, new TypeReference<AccessTokenVo>() {
            });
            if (accessTokenVo == null || !ticket.equals(accessTokenVo.getTicket()) || !random.equals(accessTokenVo.getRandom())) {
                BaseContextHandler.remove();
                return tokenPermission == null;
            }
            String accessToken = accessTokenVo.getAccessToken();
            try {
                claims = JwtHelper.parserToken(accessToken, secretConfig.getAccessTokenPubKey());
                BaseContextHandler.setClaims(claims);
            } catch (Exception e) {
                BaseContextHandler.remove();
                return tokenPermission == null;
            }
            try {
                accessToken = JwtHelper.generateToken(claims, secretConfig.getAccessTokenPriKey(), TokenConstants.EXPIRE_IN_DEFAULT);
                Integer expireIn = accessTokenVo.getExpireIn();
                expireIn = expireIn == null ? secretConfig.getAccessTokenExpire() : expireIn;
                accessTokenVo.setAccessToken(accessToken);
                redisService.setEx(redisKey, expireIn, JSON.toJSONString(accessTokenVo));
            } catch (Exception e) {
            }
            return true;
        } catch (Exception e) {
            LOGGER.error("getAndResetAccessToken originTicket[{}] error:", originTicket, e);
        }
        BaseContextHandler.remove();
        return tokenPermission == null;
    }
}
